package cc.autoapi.pucong.auto.flow.spring.boot.start.config;


import cc.autoapi.pucong.auto.flow.core.root.entity.UserJwt;
import cc.autoapi.pucong.auto.flow.core.root.exception.AutoFlowBaseController;
import cc.autoapi.pucong.auto.flow.core.root.properties.AutoFlowDesignConfiguration;
import cc.autoapi.pucong.auto.flow.core.root.utils.Res;
import cc.autoapi.pucong.auto.flow.core.root.utils.SystemConstant;
import cc.autoapi.pucong.auto.flow.persistence.bo.jwt.CheckResult;
import cc.autoapi.pucong.auto.flow.persistence.utils.JwtUtils;
import cc.autoapi.pucong.auto.flow.provider.sys.entity.SysReturnUrl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author pucong
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    private final DesignCorsFilter designCorsFilter;
    private AutoFlowDesignConfiguration autoFlowDesignConfiguration;


    public LoginInterceptor(AutoFlowDesignConfiguration autoFlowDesignConfiguration, DesignCorsFilter designCorsFilter) {
        this.designCorsFilter = designCorsFilter;
        this.autoFlowDesignConfiguration = autoFlowDesignConfiguration;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        HandlerMethod handlerMethod;
        if (handler instanceof HandlerMethod) {
            handlerMethod = (HandlerMethod) handler;
            handler = handlerMethod.getBean();
            if (!(handler instanceof AutoFlowBaseController)) {
                return true;
            }
        } else {
            return true;
        }
        if (!autoFlowDesignConfiguration.isEnable()) {
            return false;
        }
        if (designCorsFilter != null) {
            designCorsFilter.process(request, response);
        }
        String uri = request.getRequestURI();
        log.debug("进入拦截器preHandle,uri:" + uri);
        //从cookie中获取token
        String lsso_token = JwtUtils.getToken();

        // 拦截去登录
        if (null == lsso_token || "".equals(lsso_token)) {
            log.info("token为空，拦截去登录");
            SysReturnUrl url = new SysReturnUrl();
            url.setLssoUrl(SystemConstant.SYS_LOGIN_PATH);
            returnJson(response, SystemConstant.NO_LOGIN, "请先登录", url);
            return false;
        } else {
            // 校验token
            CheckResult checkResult = JwtUtils.verifyToken(lsso_token);
            if (checkResult.isSuccess()) {
                // 刷新token
                String refreshToken = JwtUtils.autoRefreshToken(checkResult, lsso_token);
                // 获取用户信息
                UserJwt loginUser = checkResult.getClaims().getUserJwt();

                loginUser.setToken(refreshToken);
                request.setAttribute(SystemConstant.JWT_TOKEN, loginUser);
                return true;
            } else {
                // token过期
                SysReturnUrl url = new SysReturnUrl();
                url.setLssoUrl(SystemConstant.SYS_LOGIN_PATH);
                if (checkResult.getErrCode().equals(SystemConstant.JWT_ERRCODE_EXPIRE)) {
                    returnJson(response, SystemConstant.NO_LOGIN, "token已过期，请先登录", url);
                } else {
                    returnJson(response, SystemConstant.NO_LOGIN, "token无效，请先登录", url);
                }
                return false;
            }
        }
    }


    private void returnJson(HttpServletResponse response, String code, String message, SysReturnUrl url) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            Res res = Res.custom(code, message, url);
            ObjectMapper objectMapper = new ObjectMapper();
            String resStr = objectMapper.writeValueAsString(res);

            writer.print(resStr);
        } catch (IOException e) {
            log.error("拦截器输出流异常[{}]", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    private void response401(HttpServletResponse response) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        try {
            String msg = "user not login";
            ObjectMapper mapper = new ObjectMapper();
            Res custom = Res.custom(SystemConstant.NO_LOGIN, msg);
            String json = mapper.writeValueAsString(custom);
            response.getWriter().print(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

}
